<?php declare(strict_types=1);

/**
 * @package AdsBlock (Light Portal)
 * @link https://custom.simplemachines.org/index.php?mod=4244
 * @author Bugo <bugo@dragomano.ru>
 * @copyright 2020-2025 Bugo
 * @license https://spdx.org/licenses/GPL-3.0-or-later.html GPL-3.0-or-later
 *
 * @category plugin
 * @version 01.11.25
 */

namespace LightPortal\Plugins\AdsBlock\Hooks;

use Bugo\Compat\Utils;
use LightPortal\Plugins\AdsBlock\Placement;
use LightPortal\Utils\Traits\HasPortalSql;
use LightPortal\Utils\Traits\HasRequest;

class MenuButtons
{
	use HasPortalSql;
	use HasRequest;

	public function __invoke(): void
	{
		$this->prepareAdsPlacements();

		if ((empty(Utils::$context['current_board']) && empty(Utils::$context['lp_page'])))
			return;

		if ($this->request()->is('xml'))
			return;

		Utils::$context['lp_ads_blocks'] = $this->getData();

		if (Utils::$context['lp_ads_blocks']) {
			Utils::$context['lp_blocks'] = array_merge(Utils::$context['lp_blocks'], Utils::$context['lp_ads_blocks']);
		}

		$this->handleBlocks();
	}

	private function prepareAdsPlacements(): void
	{
		if ($this->request()->hasNot('area'))
			return;

		if ($this->request()->get('area') !== 'lp_settings')
			return;

		if (Utils::$context['current_subaction'] !== 'panels')
			return;

		unset(Utils::$context['lp_block_placements']['ads']);

		Utils::$context['lp_block_placements'] = array_merge(
			Utils::$context['lp_block_placements'], Placement::all()
		);
	}

	private function getData(): array
	{
		if (empty(Utils::$context['lp_blocks']['ads'])) {
			return [];
		}

		$blocks = [];
		foreach (array_keys(Placement::all()) as $position) {
			$blocks[$position] = $this->getByPosition($position);
		}

		return $blocks;
	}

	private function handleBlocks(): void
	{
		if (empty(Utils::$context['lp_blocks']['ads']))
			return;

		foreach (Utils::$context['lp_blocks']['ads'] as $block) {
			if (empty($block['parameters']))
				continue;

			if (! empty($block['parameters']['loader_code'])) {
				Utils::$context['html_headers'] .= "\n\t" . $block['parameters']['loader_code'];
			}

			if (! empty($block['parameters']['end_date']) && $this->getEndTime($block['parameters']) <= time()) {
				$this->disableBlock($block['id']);
			}
		}
	}

	private function getByPosition(string $position): array
	{
		if (empty($position)) {
			return [];
		}

		return array_filter(
			Utils::$context['lp_blocks']['ads'],
			fn($block) => (
				$this->filterByIncludedTopics($block) &&
				$this->filterByIncludedBoards($block) &&
				$this->filterByIncludedPages($block) &&
				$this->filterByAdsPlacement($position, $block)
			)
		);
	}

	private function filterByIncludedTopics(array $block): bool
	{
		if (! empty($block['parameters']['include_topics']) && ! empty(Utils::$context['current_topic'])) {
			$topics = array_flip(explode(',', (string) $block['parameters']['include_topics']));

			if (! array_key_exists(Utils::$context['current_topic'], $topics)) {
				return false;
			}
		}

		return true;
	}

	private function filterByIncludedBoards(array $block): bool
	{
		if (
			! empty($block['parameters']['include_boards'])
			&& ! empty(Utils::$context['current_board'])
			&& empty(Utils::$context['current_topic'])
		) {
			$boards = array_flip(explode(',', (string) $block['parameters']['include_boards']));

			if (! array_key_exists(Utils::$context['current_board'], $boards)) {
				return false;
			}
		}

		return true;
	}

	private function filterByIncludedPages(array $block): bool
	{
		if (! empty($block['parameters']['include_pages']) && ! empty(Utils::$context['lp_page'])) {
			$pages = array_flip(explode(',', (string) $block['parameters']['include_pages']));

			if (! array_key_exists(Utils::$context['lp_page']['id'], $pages)) {
				return false;
			}
		}

		return true;
	}

	private function filterByAdsPlacement(string $position, array $block): bool
	{
		if ($block['parameters']['ads_placement']) {
			$placements = array_flip(explode(',', (string) $block['parameters']['ads_placement']));

			if (! array_key_exists($position, $placements)) {
				return false;
			}
		}

		return true;
	}

	private function getEndTime(array $params): int
	{
		return $params['end_date'] ? strtotime((string) $params['end_date']) : time();
	}

	private function disableBlock(int $item): void
	{
		$update = $this->getPortalSql()->update('lp_blocks')
			->set(['status' => 0])
			->where(['block_id' => $item]);

		$this->getPortalSql()->execute($update);
	}
}
